package com.googlecode.wheres_my_stuff_okay_potato;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.util.LinkedList;
import java.util.List;

import android.content.Context;

/**
 * Item I/O class that handles item database operations.
 * 
 * @author Chad Miller
 */
public class ItemHandler {
	private static final String ASSETS_DIR = "assets";
	private static final String DB_FILE = "items.db";
	private final Context context;
	private List<Item> items;

	/**
	 * Creates a new instance of ItemHandler.
	 * 
	 * @param context
	 *            is the context this should be created with to properly write
	 *            and read the item database file.
	 */
	public ItemHandler(Context context) {
		this.context = context;

		try {
			items = loadDatabase();
		} catch (FileNotFoundException e) {
			try {
				saveDatabase();
			} catch (Exception ex) {
				items = new LinkedList<Item>();
				ex.printStackTrace();
			}
		} catch (Exception e) {
			items = new LinkedList<Item>();
			e.printStackTrace();
		}
	}

	/**
	 * Adds a new item and saves the database file.
	 * 
	 * @param item
	 *            is the item that should be added.
	 */
	public void addItem(Item item) {
		items.add(item);

		try {
			saveDatabase();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Returns the list of items saved in the database.
	 * 
	 * @return the list of items saved in the database.
	 */
	public List<Item> getItems() {
		return items;
	}

	public List<Item> getItemsByCat(String cat) {
		List<Item> returnable = new LinkedList<Item>();
		for (Item i : items) {
			if (i.getItemCategory().equals(cat)) {
				returnable.add(i);
			}
		}
		return returnable;
	}

	/**
	 * Returns the list of lost items saved in the database.
	 * 
	 * @return the list of lost items saved in the database.
	 */
	public List<Item> getLostItems() {
		List<Item> lostItems = new LinkedList<Item>();
		for (Item i : items) {
			if (i.isLostItem() && i.isOpen())
				lostItems.add(i);
		}
		return lostItems;
	}

	/**
	 * Returns the list of found items saved in the database.
	 * 
	 * @return the list of found items saved in the database.
	 */
	public List<Item> getFoundItems() {
		List<Item> foundItems = new LinkedList<Item>();
		for (Item i : items) {
			if (i.isFoundItem() && i.isOpen())
				foundItems.add(i);
		}
		return foundItems;
	}

	/**
	 * Returns the list of items in the database associated with a specified
	 * user.
	 * 
	 * @param owner
	 *            is the user whose items should be returned.
	 * @return a list of items in the database associated with the specified
	 *         user.
	 */
	public List<Item> getItems(User owner) {
		List<Item> out = new LinkedList<Item>();

		for (Item item : items) {
			if (item.ownedBy(owner))
				out.add(item);
		}

		return out;
	}

	/**
	 * Writes the item database file to the assets folder.
	 */
	public void saveDatabase() throws FileNotFoundException, IOException {
		final File dir = new File(context.getFilesDir() + File.separator
				+ ASSETS_DIR);
		dir.mkdirs();
		final File file = new File(dir, DB_FILE);

		ObjectOutputStream output = new ObjectOutputStream(
				new FileOutputStream(file));
		output.writeObject(items);
		output.close();
	}

	/**
	 * Reads an item database file. There is only one and its location will
	 * always remain constant, so this takes no parameters.
	 * 
	 * @throws IOException
	 *             if a general I/O error occurs.
	 * @throws FileNotFoundException
	 *             if the database file was not found.
	 * @throws StreamCorruptedException
	 *             if the stream is corrupted.
	 * @throws ClassNotFoundException
	 *             if the database file could not be parsed properly.
	 */
	@SuppressWarnings("unchecked")
	public List<Item> loadDatabase() throws StreamCorruptedException,
			FileNotFoundException, IOException, ClassNotFoundException {
		final File dir = new File(context.getFilesDir() + File.separator
				+ ASSETS_DIR);

		ObjectInputStream input = new ObjectInputStream(new FileInputStream(
				new File(dir, DB_FILE)));
		List<Item> out = (List<Item>) input.readObject();
		input.close();
		return out;
	}
}